#include <CH549_DEBUG.h>
#include <CH549_sdcc.h>
#include <HID.H>
#include <UsbToPs2.h>
#include <key_conv.H>
#include <ps2.H>

#define quaterT 16
#define halfT 32

// PS2编码表
//  下标：序列号0
//  值：对应的PS/2扫描码
//      0x00：不支持
//      0xE0：扩展码——需要另外查表
UINT8C PS2_SET2_MAKE[] = {
    0x00, // 00 N/A
    0x1C, // 01 A
    0x32, // 02 B
    0x21, // 03 C
    0x23, // 04 D
    0x24, // 05 E
    0x2B, // 06 F
    0x34, // 07 G
    0x33, // 08 H
    0x43, // 09 I
    0x3B, // 10 J
    0x42, // 11 K
    0x4B, // 12 L
    0x3A, // 13 M
    0x31, // 14 N
    0x44, // 15 O
    0x4D, // 16 P
    0x15, // 17 Q
    0x2D, // 18 R
    0x1B, // 19 S
    0x2C, // 20 T
    0x3C, // 21 U
    0x2A, // 22 V
    0x1D, // 23 W
    0x22, // 24 X
    0x35, // 25 Y
    0x1A, // 26 Z
    0x45, // 27 0
    0x16, // 28 1
    0x1E, // 29 2
    0x26, // 30 3
    0x25, // 31 4
    0x2E, // 32 5
    0x36, // 33 6
    0x3D, // 34 7
    0x3E, // 35 8
    0x46, // 36 9
    0x0E, // 37 ` ~    JPN 半角/全角|汉字
    0x4E, // 38 - _    JPN - =
    0x55, // 39 = +    JPN ^ ~
    0x5D, // 40 \ |
    0x66, // 41 backspace
    0x29, // 42 space
    0x0D, // 43 tab
    0x58, // 44 caps lock
    0x12, // 45 L shift
    0x14, // 46 L ctrl
    0xE0, // 47 L WIN
    0x11, // 48 L Alt
    0x59, // 49 R shift
    0xE0, // 50 R ctrl
    0xE0, // 51 R WIN
    0xE0, // 52 R Alt
    0xE0, // 53 application
    0x5A, // 54 return
    0x76, // 55 Esc
    0x05, // 56 F1
    0x06, // 57 F2
    0x04, // 58 F3
    0x0C, // 59 F4
    0x03, // 60 F5
    0x0B, // 61 F6
    0x83, // 62 F7
    0x0A, // 63 F8
    0x01, // 64 F9
    0x09, // 65 F10
    0x78, // 66 F11
    0x07, // 67 F12
    0xE0, // 68 print screen
    0x7E, // 69 scroll lock
    0xE0, // 70 pause
    0x54, // 71 [ {     JPN @ ·
    0xE0, // 72 insert
    0xE0, // 73 home
    0xE0, // 74 page up
    0xE0, // 75 del
    0xE0, // 76 end
    0xE0, // 77 page down
    0xE0, // 78 up
    0xE0, // 79 left
    0xE0, // 80 down
    0xE0, // 81 right
    0x77, // 82 num lock
    0xE0, // 83 num /
    0x7C, // 84 num *
    0x7B, // 85 num -
    0x79, // 86 num +
    0xE0, // 87 num enter
    0x71, // 88 num . del
    0x70, // 89 num 0
    0x69, // 90 num 1
    0x72, // 91 num 2
    0x7A, // 92 num 3
    0x6B, // 92 num 4
    0x73, // 94 num 5
    0x74, // 95 num 6
    0x6C, // 96 num 7
    0x75, // 97 num 8
    0x7D, // 98 num 9
    0x5B, // 99 ] }      JPN [ {
    0x4C, // 100 ; :     JPN ; +
    0x52, // 101 ' "     JPN : *
    0x41, // 102 , <
    0x49, // 103 . >
    0x4A, // 104 / ?
    0x5D, // 105
    0x51, // 106         JPN \ -
    0x13, // 107         JPN 输入方式变换
    0x6A, // 108         JPN 羊 |
    0x64, // 109         JPN 变换
    0x67, // 110         JPN 无变换
    0x00, // 111 N/A
    0x00, // 112 N/A
    0x00, // 113 N/A
    0x00, // 114 N/A
    0x00, // 115 N/A
    0x00, // 116 N/A
    0x00, // 117 N/A
    0x00, // 118 N/A
    0x00, // 119 N/A
    0xE0, // 120 power
};

// 机打速率表 (ms)
const unsigned short __code PS2_KeyRepeatRate[] = {
    500, // 0x00  2.0cps
    476, // 0x01  2.1cps
    434, // 0x02  2.3cps
    400, // 0x03  2.5cps
    370, // 0x04  2.7cps
    333, // 0x05  3.0cps
    303, // 0x06  3.3cps
    270, // 0x07  3.7cps
    250, // 0x08  4.0cps
    232, // 0x09  4.3cps
    217, // 0x0A  4.6cps
    200, // 0x0B  5.0cps
    181, // 0x0C  5.5cps
    166, // 0x0D  6.0cps
    149, // 0x0E  6.7cps
    133, // 0x0F  7.5cps
    125, // 0x10  8.0cps
    116, // 0x11  8.6cps
    108, // 0x12  9.2cps
    100, // 0x13  10.0cps
    91,  // 0x14  10.9cps
    83,  // 0x15  12.0cps
    75,  // 0x16  13.3cps
    66,  // 0x17  15.0cps
    62,  // 0x18  16.0cps
    58,  // 0x19  17.1cps
    54,  // 0x1A  18.5cps
    50,  // 0x1B  20.0cps
    45,  // 0x1C  21.8cps
    41,  // 0x1D  24.0cps
    37,  // 0x1E  26.7cps
    33   // 0x1F  30.0cps
};

// 机打延时表 (ms)
const unsigned short __code PS2_KeyDelay[] = {
    250, // 0x00  250ms
    500, // 0x01  500ms
    750, // 0x02  750ms
    1000 // 0x03  1000ms
};

// #pragma  NOAREGS

/*******************************************************************************
 * Function Name  : ps2_readClk
 * Description    :
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
inline BOOL ps2_readClk() {
    BOOL b = ps2_clk;

    if (ps2_dev) {
        led_ps2MS = !b;
    } else {
        led_ps2KB = !b;
    }

    return b;
}

inline void ps2_setClk(UINT8 clk) {
    ps2_clk = clk;
    if (ps2_dev) {
        led_ps2MS = !clk;
    } else {
        led_ps2KB = !clk;
    }
}

/*******************************************************************************
 * Function Name  : InitPS2
 * Description    : 初始化PS2设备,串口默认引脚 P26 P27
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void InitPS2(void) {

    ps2_setClk(1);
    ps2_d = 1;

    ps2_resetDevice();
}

/*******************************************************************************
 * Function Name  : ps2_checkChangeKB
 * Description    : 比较按键变化，生产ps/2编码
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void ps2_checkChangeKB(void) {
    if (!pPS2_KB_INFO->Enable) {
        return;
    }

    UINT8 i;
    // 比较所有120个按键
    for (i = 0; i < 120; i++) {
        if (pPS2_KB_INFO->KeyStatus[i] == 0 && pPS2_KB_INFO->KeyStatusTmp[i] == 1) {
            // 按下
            ps2_copy_code(i, 1);
        } else if (pPS2_KB_INFO->KeyStatus[i] == 1 && pPS2_KB_INFO->KeyStatusTmp[i] == 0) {
            // 释放
            ps2_copy_code(i, 0);
        }
        pPS2_KB_INFO->KeyStatus[i] = pPS2_KB_INFO->KeyStatusTmp[i];
    }
}

/*******************************************************************************
 * Function Name  : ps2_checkChangeMS
 * Description    : 比较坐标变化，生成ps/2编码
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void ps2_checkChangeMS(void) {
    UINT8 data[4]; // 准备发送的数据
    UINT8 i = 0;
    __bit changed = 0;

    if (!pPS2_MS_INFO->Enable) {
        return;
    }

    data[0] = 0x08; // 有一位一直是1
    data[3] = 0x00;

    // 左右位移
    data[1] = pPS2_MS_INFO->Position[0];
    if (pPS2_MS_INFO->Position[0] < 0) {
        changed = 1;
        data[0] |= 0x10;
    } else if (pPS2_MS_INFO->Position[0] > 0) {
        changed = 1;
    }
    pPS2_MS_INFO->Position[0] = 0;

    // 上下位移
    data[2] = pPS2_MS_INFO->Position[1];
    if (pPS2_MS_INFO->Position[1] < 0) {
        changed = 1;
        data[0] |= 0x20;
    } else if (pPS2_MS_INFO->Position[1] > 0) {
        changed = 1;
    }
    pPS2_MS_INFO->Position[1] = 0;

    if (pPS2_MS_INFO->Scaling) {
        // 2:1 比例
        for (i = 1; i < 3; i++) {
            switch (data[i]) {
            case 0:
            case 1:
            case 3:
                break;
            case 2:
                data[i] = 1;
                break;
            case 4:
                data[i] = 6;
                break;
            case 5:
                data[i] = 9;
                break;
            default:
                data[i] <<= 1;
                break;
            }
        }
    }

    // 滚轮
    if (pPS2_MS_INFO->Position[2]) {
        changed = 1;
        if (pPS2_MS_INFO->devID == 0x04) {
            data[3] |= pPS2_MS_INFO->Position[2] & 0x0F;
        } else {
            data[3] = (UINT8)pPS2_MS_INFO->Position[2];
        }
        pPS2_MS_INFO->Position[2] = 0;
    }

    for (i = 0; i < 5; i++) {
        if (changed || pPS2_MS_INFO->KeyStatusTmp[i] != pPS2_MS_INFO->KeyStatus[i]) {
            changed = 1;
            switch (i) {
            case 0: // 鼠标左键
                if (pPS2_MS_INFO->KeyStatusTmp[i]) {
                    data[0] |= 0x01;
                }
                break;
            case 1: // 鼠标右键
                if (pPS2_MS_INFO->KeyStatusTmp[i]) {
                    data[0] |= 0x02;
                }
                break;
            case 2: // 鼠标中键
                if (pPS2_MS_INFO->KeyStatusTmp[i]) {
                    data[0] |= 0x04;
                }
                break;
            case 3: // 鼠标键4
                if (pPS2_MS_INFO->KeyStatusTmp[i]) {
                    data[3] |= 0x10;
                }
                break;
            case 4: // 鼠标键5
                if (pPS2_MS_INFO->KeyStatusTmp[i]) {
                    data[3] |= 0x20;
                }
                break;
            }
        }
        pPS2_MS_INFO->KeyStatus[i] = pPS2_MS_INFO->KeyStatusTmp[i];
    }

    if (changed) {
        // stream模式时主动发送
        PS2_TXBuffer[PS2_TX_E++] = data[0];
        PS2_TXBuffer[PS2_TX_E++] = data[1];
        PS2_TXBuffer[PS2_TX_E++] = data[2];
        if (pPS2_MS_INFO->devID != 0x00) {
            PS2_TXBuffer[PS2_TX_E++] = data[3];
        }
    }
}
/*******************************************************************************
 * Function Name  : ps2_kb_checkRepeatKey
 * Description    : 检查机打按键，若到时则发送
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void ps2_kb_checkRepeatKey(void) {

    if (!pPS2_KB_INFO->Enable) {
        return;
    }

    if (!pPS2_KB_INFO->KeyRepeat) {
        return;
    }

    if (pPS2_KB_INFO->KeyRepeatCnt == 0) { //
        // 重置机打频率计数
        pPS2_KB_INFO->KeyRepeatCnt = pPS2_KB_INFO->KeyRepeatRate;

        // 机打指令进缓存
        ps2_copy_code(pPS2_KB_INFO->KeyRepeat, 1);
    }
}

/*******************************************************************************
 * Function Name  : ps2_copy_code
 * Description    : 将编码复制到缓存（循环储存）
 * Input          : index   PS/2扫描码序列号
 *                : type    0:断码  1：通码
 * Output         : None
 * Return         : None
 * 注： PS2_TX_E(UINT8) 范围是0~255，正好用来循环储存PS2_TXBuffer[256]而不用担心溢出
 *******************************************************************************/
void ps2_copy_code(UINT8 index, UINT8 type) {
    UINT8 c = 0;

    // 转换为PS/2扫描码
    c = PS2_SET2_MAKE[index];
    if (c == 0xE0) {

        switch (index) {
        case 47: // L GUI
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x1F;
            break;
        case 50: // R Ctrl
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x14;
            break;
        case 51: // R GUI
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x27;
            break;
        case 52: // R Alt
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x11;
            break;
        case 53: // application
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x2F;
            break;
        case 68: // print screen
            if (type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xE0;
                PS2_TXBuffer[PS2_TX_E++] = 0x12;
                PS2_TXBuffer[PS2_TX_E++] = 0xE0;
                PS2_TXBuffer[PS2_TX_E++] = 0x7C;
            } else {
                PS2_TXBuffer[PS2_TX_E++] = 0xE0;
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
                PS2_TXBuffer[PS2_TX_E++] = 0x7C;
                PS2_TXBuffer[PS2_TX_E++] = 0xE0;
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
                PS2_TXBuffer[PS2_TX_E++] = 0x12;
            }
            break;
        case 70: // pause
            if (type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xE1;
                PS2_TXBuffer[PS2_TX_E++] = 0x14;
                PS2_TXBuffer[PS2_TX_E++] = 0x77;
                PS2_TXBuffer[PS2_TX_E++] = 0xE1;
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
                PS2_TXBuffer[PS2_TX_E++] = 0x14;
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
                PS2_TXBuffer[PS2_TX_E++] = 0x77;
            }
            break;
        case 72: // insert
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x70;
            break;
        case 73: // home
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x6C;
            break;
        case 74: // page up
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x7D;
            break;
        case 75: // del
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x71;
            break;
        case 76: // end
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x69;
            break;
        case 77: // page down
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x7A;
            break;
        case 78: // up
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x75;
            break;
        case 79: // left
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x6B;
            break;
        case 80: // down
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x72;
            break;
        case 81: // right
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x74;
            break;
        case 83: // num /
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x4A;
            break;
        case 87: // num enter
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x5A;
            break;
        case 120: // power
            PS2_TXBuffer[PS2_TX_E++] = 0xE0;
            if (!type) {
                PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            }
            PS2_TXBuffer[PS2_TX_E++] = 0x37;
            break;
        }
    } else {
        if (type) {
            // 1：通码
            PS2_TXBuffer[PS2_TX_E++] = c;

        } else {
            // 0:断码
            PS2_TXBuffer[PS2_TX_E++] = 0xF0;
            PS2_TXBuffer[PS2_TX_E++] = c;
        }
    }
}

// 发送一位
UINT8 psd_send_bit() {
    // 等待主机释放clk
    while (!ps2_readClk()) {
        mDelayuS(1);
    }

    ps2_d = ps2_dataBit;
    mDelayuS(quaterT);
    ps2_setClk(0);
    mDelayuS(halfT);
    ps2_setClk(1);
    mDelayuS(quaterT);

    return 1;
}

// 读取一位
UINT8 psd_read_bit() {
    mDelayuS(quaterT);
    ps2_setClk(0);
    mDelayuS(halfT);
    ps2_setClk(1);
    mDelayuS(quaterT);

    if (!ps2_readClk())
        return 0;

    if (ps2_d) {
        ps2_dataBit = 0x80;
    } else {
        ps2_dataBit = 0x00;
    }

    return 1;
}

/*******************************************************************************
 * Function Name  : ps2_sendByte
 * Description    : 发送一个字节
 * Input          : ps2_dataBuf
 * Output         : None
 * Return         : 0： success  1：fail
 *******************************************************************************/
UINT8 ps2_sendByte(UINT8 data) {

    // 检测1
    if (!ps2_readClk()) {
        // 被主机抢占
        return 1;
    }

    ps2_d = 1;
    mDelayuS(halfT + quaterT);

    // 检测2
    if (!ps2_readClk()) {
        // 被主机抢占
        return 1;
    }

    if (!ps2_d) {
        // 主机在输出
        return 1;
    }

    // 现在是clk(1),d(1)
    ps2_dataBit = 0;
    if (!psd_send_bit()) { // 发送起始位
        ps2_d = 1;
        return 1;
    }

    UINT8 i = 0;
    ps2_dataBuf = 0; // 发送的数据
    ps2_dataChk = 1; // 奇偶校验
    ps2_dataBit = 0; // 接收/发送的数据位

    // 发送数据
    ps2_dataBuf = data;
    for (; i < 8; i++) {
        ps2_dataBit = ps2_dataBuf & 0x01;
        ps2_dataChk ^= ps2_dataBit;
        if (!psd_send_bit()) {
            ps2_d = 1;
            return 1;
        }
        ps2_dataBuf >>= 1;
    }

    // 发送校验位
    ps2_dataBit = ps2_dataChk;
    if (!psd_send_bit()) {
        ps2_d = 1;
        return 1;
    }

    // 查看是否被主机拉低
    ps2_d = 1; // 释放
    if (!ps2_readClk()) {
        return 1;
    }

    // 发送停止位
    mDelayuS(quaterT);
    ps2_setClk(0);   // 此时主机将读取DATA线
    mDelayuS(halfT); // 等待主机读取完毕
    ps2_setClk(1);
    mDelayuS(halfT);

    return 0;
}

/*******************************************************************************
 * Function Name  : ps2_sendData
 * Description    : 将缓存中的数据发送出去
 * Input          :
 * Output         : None
 * Return         : None
 *******************************************************************************/
void ps2_sendData(void) {

    while (PS2_TX_S != PS2_TX_E) {
        if (0 == ps2_sendByte(PS2_TXBuffer[PS2_TX_S])) {
            printf("sent:%d:%02X\n", PS2_TX_S, PS2_TXBuffer[PS2_TX_S]);
            PS2_TX_S++;

            // 等待主机处理完毕
            while (!ps2_readClk())
                mDelayuS(1);

            // 如果还有要发送的数据
            if (PS2_TX_S != PS2_TX_E) {
                mDelayuS(150);
            }

        } else {
            break;
        }
    }
}

/*******************************************************************************
 * Function Name  : ps2_readData
 * Description    : 接收数据到缓存
 * Input          :
 * Output         : None
 * Return         : 3: 失败（主机端错误）
 *                  2：失败(校验出错)
 *                  0: 没有数据
 *                  1: success(读到正确数据)
 *******************************************************************************/
UINT8 ps2_readData(void) {
    UINT8 i = 0;

    // 检测1
    if (!ps2_readClk() || ps2_d) {
        // 主机并未输出
        return 0;
    }

    // 现在是clk(1),d(0), 起始位的上升沿已过
    ps2_dataBuf = 0; // 接收的数据
    ps2_dataChk = 0; // 奇偶校验
    ps2_dataBit = 0; // 接收的数据位

    // 读取8位数据
    mDelayuS(quaterT);
    for (; i < 8; i++) {
        if (!psd_read_bit()) {
            return 0;
        }
        ps2_dataBuf >>= 1;
        ps2_dataBuf |= ps2_dataBit;
        ps2_dataChk ^= ps2_dataBit;
    }

    // 读取校验位
    if (!psd_read_bit()) {
        return 0;
    }
    ps2_dataChk ^= ps2_dataBit;

    // 读取停止位
    if (!psd_read_bit()) {
        return 0;
    }

    // 输出应答位
    ps2_dataBit = 0;
    psd_send_bit();
    ps2_d = 1; // 释放D
    mDelayuS(quaterT);

    // 校验
    if (ps2_dataChk) {
        PS2_RXBuffer = ps2_dataBuf;
    }

    // 等待主机处理完毕
    mDelayuS(halfT + quaterT);
    while (!ps2_readClk())
        mDelayuS(1);

    if (ps2_dataChk) {
        return 1;
    }

    return 2;
}

// 设备复位
void ps2_resetDevice() {
    UINT8 i;
    if (ps2_dev) {
        // 初始化键盘
        pPS2_KB_INFO->Enable = 1;                              // 0: 停止发送  1: 使能
        pPS2_KB_INFO->LED = 0;                                 //
        pPS2_KB_INFO->KeyRepeat = 0;                           // 机打按键
        pPS2_KB_INFO->KeyRepeatRate = PS2_KeyRepeatRate[0x14]; // 机打频率 —— 默认10.9cps
        pPS2_KB_INFO->KeyDelay = PS2_KeyDelay[0x01];           // 机打延时 —— 默认500ms
        pPS2_KB_INFO->KeyRepeatCnt = 0;                        // 机打延时计数
        for (i = 0; i < 120; i++) {
            pPS2_KB_INFO->KeyStatus[i] = 0;    // 记录每个按键当前状态 0：释放， 1按下
            pPS2_KB_INFO->KeyStatusTmp[i] = 0; // 按键的新状态 0：释放， 1按下
            pPS2_KB_INFO->Keymode[i] = 0;      // 按键的发送模式
        }
        led_ps2KB = 0;
        led_ps2MS = 1;
    } else {
        // 初始化鼠标
        pPS2_MS_INFO->Enable = 0;            // 0: 停止发送  1: 使能
        pPS2_MS_INFO->devID = 0x04;          // 0x00: 标准PS/2(3键，无滚轮)  0x03:Intellimouse（3键，有滚轮） 0x04：Intellimouse扩展（5键，有滚轮）
        pPS2_MS_INFO->mode = 0x00;           // 模式：00:初始化  01：stream（有变化就发送） 02：remote（查询才发送） 03：wrap（会送字节）
        pPS2_MS_INFO->last_mode = 0x00;      // 模式： 前一模式状态
        pPS2_MS_INFO->SamplingRate[0] = 100; // 采样率
        pPS2_MS_INFO->SamplingRate[1] = 0;
        pPS2_MS_INFO->SamplingRate[2] = 0;
        pPS2_MS_INFO->Resolution = 2; // 分辨率 (4点/mm)
        pPS2_MS_INFO->Scaling = 0;    // 缩放比例 (1:1)
        pPS2_MS_INFO->Position[0] = 0;
        pPS2_MS_INFO->Position[1] = 0;
        pPS2_MS_INFO->Position[2] = 0;
        for (i = 0; i < 5; i++) {
            pPS2_MS_INFO->KeyStatus[i] = 0;    // 记录每个按键当前状态 0：释放， 1按下
            pPS2_MS_INFO->KeyStatusTmp[i] = 0; // 按键的新状态 0：释放， 1按下
        }
        led_ps2KB = 1;
        led_ps2MS = 1;
    }
    PS2_TX_S = 0; // 清空缓存
    PS2_TX_E = 0;
}

/*******************************************************************************
 * Function Name  : ps2_readAndExec_KB
 * Description    : 接收和执行指令
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void ps2_readAndExec_KB(void) {
    UINT8 s, cnt;
    UINT8 cmd;
    UINT8 para;

    // 接收到缓存
    s = ps2_readData();
    if (s == 2) {
        // 读取到错误数据
        ps2_sendByte(0xFE); // 请求重发
        return;
    } else if (s == 1) {
        cmd = PS2_RXBuffer;
    } else {
        return;
    }

    printf("cmd[x%02X]\n", cmd);

    switch (cmd) {
    case 0xED: // 设置键盘LED
    case 0xF0: // 设置或查询编码集合
    case 0xF3: // 设置键盘机打速率和延时
        // 双字节指令，第一周期只回送 0xFA
        ps2_sendByte(0xFA);

        // 读取第二字节
        while (1) {
            s = ps2_readData();
            if (s == 2) {
                // 读取到错误数据
                ps2_sendByte(0xFE); // 请求重发
            } else if (s == 1) {
                para = PS2_RXBuffer;
                break;
            }
        }
        printf("para[x%02X]\n", para);
        break;
    }

    switch (cmd) {
    case 0xED: // 设置键盘LED
        pPS2_KB_INFO->LED = para;
        ps2_sendByte(0xFA); // 回复
        hid_setup(1, ps2toHIDCodeLED(pPS2_KB_INFO->LED));
        break;
    case 0xF0: // 设置或查询编码集合
        if (para) {
            ps2_sendByte(0xFA); // 回复
        } else {
            ps2_sendByte(0x02);
            ; // 回复 —— 使用第二套编码集
        }
        break;
    case 0xF2: // 询问device id
        PS2_TX_S = PS2_TX_E;
        PS2_TXBuffer[PS2_TX_E++] = 0xFA;
        PS2_TXBuffer[PS2_TX_E++] = 0xAB;
        PS2_TXBuffer[PS2_TX_E++] = 0x83;
        break;
    case 0xF3:                                                        // 设置键盘机打速率和延时
        pPS2_KB_INFO->KeyRepeatRate = PS2_KeyRepeatRate[para & 0x1F]; // 机打频率
        para >>= 5;
        pPS2_KB_INFO->KeyDelay = PS2_KeyDelay[para & 0x03]; // 机打延时
        // windows给的指令太慢，使用默认值：
        pPS2_KB_INFO->KeyRepeatRate = PS2_KeyRepeatRate[0x16]; // 机打频率 —— 默认10.9cps
        pPS2_KB_INFO->KeyDelay = PS2_KeyDelay[0x01];           // 机打延时 —— 默认500ms

        ps2_sendByte(0xFA); // 回复
        break;
    case 0xF4: // 使能键盘
        pPS2_KB_INFO->Enable = 1;
        ps2_sendByte(0xFA); // 回复
        led_ps2KB = 0;
        break;
    case 0xF5: // 禁止键盘
        pPS2_KB_INFO->Enable = 0;
        ps2_sendByte(0xFA); // 回复
        led_ps2KB = 1;
        led_ps2MS = 1;
        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        break;
    case 0xF6:                                                 // 设置缺省
        pPS2_KB_INFO->KeyRepeatRate = PS2_KeyRepeatRate[0x14]; // 机打频率 —— 默认10.9cps
        pPS2_KB_INFO->KeyDelay = PS2_KeyDelay[0x01];           // 机打延时 —— 默认500ms
        for (cnt = 0; cnt < 120; cnt++) {
            pPS2_KB_INFO->Keymode[cnt] = 0;
        }
        ps2_sendByte(0xFA);  // 回复
        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        break;
    case 0xF7: // 设置左右按键的发送方法
        // 不发送断码
        for (cnt = 0; cnt < 120; cnt++) {
            pPS2_KB_INFO->Keymode[cnt] = 0x02;
        }
        ps2_sendByte(0xFA);  // 回复
        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        break;
    case 0xF8: // 设置左右按键的发送方法
        // 不发送机打
        for (cnt = 0; cnt < 120; cnt++) {
            pPS2_KB_INFO->Keymode[cnt] = 0x01;
        }
        ps2_sendByte(0xFA);  // 回复
        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        break;
    case 0xF9: // 设置左右按键的发送方法
        // 不发送断码和机打
        for (cnt = 0; cnt < 120; cnt++) {
            pPS2_KB_INFO->Keymode[cnt] = 0x03;
        }
        ps2_sendByte(0xFA);  // 回复
        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        break;
    case 0xEE:              // 查响应
        ps2_sendByte(0xEE); // 回复
        break;
    // case 0xFE:      // 重新发送最后一个字节  —— 已在指令接收阶段处理
    //     break;
    case 0xFA: // 复位所有键盘的默认发送方式
        // 按键的新状态 0：释放， 1按下
        for (cnt = 0; cnt < 120; cnt++) {
            pPS2_KB_INFO->Keymode[cnt] = 0x00;
        }
        ps2_sendByte(0xFA); // 回复
        break;
    case 0xFF:              // 复位键盘
        ps2_sendByte(0xFA); // 回复成功
        ps2_resetDevice();
        hid_setup(1, 0x07); // 点亮键盘所有LED
        mDelaymS(300);
        hid_setup(1, 0x00); // 熄灭键盘所有LED

        PS2_TX_S = PS2_TX_E;             // 清空缓存——不发送
        PS2_TXBuffer[PS2_TX_E++] = 0xAA; // 复位成功
        break;
    default:
        ps2_sendByte(0xFA); // 回复
        break;
    }
}

/*******************************************************************************
 * Function Name  : ps2_readAndExec_MS
 * Description    : 接收和执行指令
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void ps2_readAndExec_MS(void) {
    UINT8 s;
    UINT8 cmd;
    UINT8 para = 0;
    UINT8 data;

    // 接收到缓存
    s = ps2_readData();
    if (s == 2) {
        // 读取到错误数据
        ps2_sendByte(0xFE); // 请求重发
        return;
    } else if (s == 1) {
        cmd = PS2_RXBuffer;
    } else {
        return;
    }

    printf("cmd[x%02X]\n", cmd);
    if (pPS2_MS_INFO->mode == 0x03) {
        // wrap模式下，回送字节
        switch (cmd) {
        case 0xFF: // 复位
        case 0xEC: // 从wrap模式返回前一模式
            break;
        default:
            ps2_sendByte(cmd);
            return;
        }
    }

    switch (cmd) {
    case 0xE8: // 设置分辨率
    case 0xF3: // 设置采样率
        // 双字节指令，第一周期只回送 0xFA
        ps2_sendByte(0xFA);

        // 读取第二字节
        while (1) {
            s = ps2_readData();
            if (s == 2) {
                // 读取到错误数据
                ps2_sendByte(0xFE); // 请求重发
            } else if (s == 1) {
                para = PS2_RXBuffer;
                break;
            }
        }
        printf("para[x%02X]\n", para);
        break;
    }

    switch (cmd) {
    case 0xE6:              // 设置缩放比例为1:1
        ps2_sendByte(0xFA); // 回复
        pPS2_MS_INFO->Scaling = 0;
        break;
    case 0xE7:              // 设置缩放比例为2:1
        ps2_sendByte(0xFA); // 回复
        pPS2_MS_INFO->Scaling = 1;
        break;
    case 0xE8:              // 设置分辨率
        ps2_sendByte(0xFA); // 回复
        pPS2_MS_INFO->Resolution = para;
        break;
    case 0xE9:              // 获取状态
        ps2_sendByte(0xFA); // 回复
        data = 0;
        if (pPS2_MS_INFO->KeyStatus[0]) {
            // 左键
            data |= 0x04;
        }
        if (pPS2_MS_INFO->KeyStatus[0]) {
            // 右键
            data |= 0x01;
        }
        if (pPS2_MS_INFO->KeyStatus[0]) {
            // 中键
            data |= 0x02;
        }
        if (pPS2_MS_INFO->Scaling) {
            // 缩放比例
            data |= 0x10;
        }
        if (pPS2_MS_INFO->Enable) {
            // 使能
            data |= 0x20;
        }
        if (pPS2_MS_INFO->mode == 0x02) {
            // remote mode
            data |= 0x40;
        }

        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        PS2_TXBuffer[PS2_TX_E++] = data;
        PS2_TXBuffer[PS2_TX_E++] = pPS2_MS_INFO->Resolution;      // 分辨率
        PS2_TXBuffer[PS2_TX_E++] = pPS2_MS_INFO->SamplingRate[0]; // 采样率
        break;
    case 0xEA:              // 进入stream模式
        ps2_sendByte(0xFA); // 回复
        pPS2_MS_INFO->mode = 0x01;
        break;
    case 0xEB: // remote模式时，查询位移
        // 未实现此功能
        break;
    case 0xEC:              // 从wrap模式返回前一模式
        ps2_sendByte(0xFA); // 回复
        pPS2_MS_INFO->mode = pPS2_MS_INFO->last_mode;
        break;
    case 0xEE:              // 进入wrap模式
        ps2_sendByte(0xFA); // 回复
        pPS2_MS_INFO->last_mode = pPS2_MS_INFO->mode;
        pPS2_MS_INFO->mode = 0x03;
        break;
    case 0xF0: // 进入remote模式
        // 未实现此功能
        // ps2_sendByte(0xFA);    // 回复
        // pPS2_MS_INFO->mode = 0x01;
        break;
    case 0xF2: // 询问device id
        // 更改设备ID
        if (pPS2_MS_INFO->SamplingRate[0] == 80 && pPS2_MS_INFO->SamplingRate[1] == 200 && pPS2_MS_INFO->SamplingRate[2] == 200) {
            pPS2_MS_INFO->devID = 0x04;
            PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        } else if (pPS2_MS_INFO->SamplingRate[0] == 80 && pPS2_MS_INFO->SamplingRate[1] == 100 && pPS2_MS_INFO->SamplingRate[2] == 200) {
            pPS2_MS_INFO->devID = 0x03;
            PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        }
        // ps2_sendByte(pPS2_MS_INFO->devID);
        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        PS2_TXBuffer[PS2_TX_E++] = 0xFA;
        PS2_TXBuffer[PS2_TX_E++] = pPS2_MS_INFO->devID;

        break;
    case 0xF3:              // 设置采样率
        ps2_sendByte(0xFA); // 回复
        switch (para) {
        case 10:
        case 20:
        case 40:
        case 60:
        case 80:
        case 100:
        case 200:
            pPS2_MS_INFO->SamplingRate[2] = pPS2_MS_INFO->SamplingRate[1];
            pPS2_MS_INFO->SamplingRate[1] = pPS2_MS_INFO->SamplingRate[0];
            pPS2_MS_INFO->SamplingRate[0] = para;
            break;
        default:
            break;
        }
        break;
    case 0xF4: // 使能
        pPS2_MS_INFO->Enable = 1;
        led_ps2MS = 0;
        ps2_sendByte(0xFA);  // 回复
        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        pPS2_MS_INFO->Position[0] = 0;
        pPS2_MS_INFO->Position[1] = 0;
        pPS2_MS_INFO->Position[2] = 0;
        break;
    case 0xF5: // 禁止
        pPS2_MS_INFO->Enable = 0;
        led_ps2KB = 1;
        led_ps2MS = 1;
        ps2_sendByte(0xFA);  // 回复
        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送
        pPS2_MS_INFO->Position[0] = 0;
        pPS2_MS_INFO->Position[1] = 0;
        pPS2_MS_INFO->Position[2] = 0;
        break;
    case 0xF6:               // 设置缺省
        ps2_sendByte(0xFA);  // 回复
        PS2_TX_S = PS2_TX_E; // 清空缓存——不发送

        pPS2_MS_INFO->SamplingRate[0] = 100; // 采样率
        pPS2_MS_INFO->SamplingRate[1] = 0;
        pPS2_MS_INFO->SamplingRate[2] = 0;
        pPS2_MS_INFO->Resolution = 2; // 分辨率 (4点/mm)
        pPS2_MS_INFO->Scaling = 0;    // 缩放比例 (1:1)
        pPS2_MS_INFO->last_mode = 0x00;
        pPS2_MS_INFO->mode = 0x01; // 模式：00:初始化  01：stream（有变化就发送） 02：remote（查询才发送） 03：wrap（会送字节）
        break;

    case 0xFF:              // 复位
        ps2_sendByte(0xFA); // 回复成功
        ps2_resetDevice();
        pPS2_MS_INFO->devID = 0x00;
        pPS2_MS_INFO->mode = 0x01; // 模式：00:初始化  01：stream（有变化就发送） 02：remote（查询才发送） 03：wrap（会送字节）
        mDelaymS(300);
        PS2_TX_S = PS2_TX_E;             // 清空缓存——不发送
        PS2_TXBuffer[PS2_TX_E++] = 0xAA; // 复位成功
        PS2_TXBuffer[PS2_TX_E++] = 0x00; // 回复设备ID

        break;
    default:
        ps2_sendByte(0xFA); // 回复
        break;
    }
}